package RadianceM.DistributionSystem.Interceptor;

import RadianceM.DistributionSystem.utils.TokenUtil;
import RadianceM.DistributionSystem.voto.result.DSResult;
import RadianceM.DistributionSystem.voto.result.ResultCode;
import com.alibaba.fastjson.JSON;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;


/**
 * JWT拦截器
 * @Author: 小碗
 * @Date: 2023/11/4 16:55:11
 */

@Slf4j
@Component
public class JWTInterceptor implements HandlerInterceptor {

	@Resource
	public TokenUtil tokenUtil;

	@Value("${jwt.tokenHeader}")
	private String tokenHeader;
	@Value("${jwt.tokenHead}")
	private String tokenHead;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json;charset=UTF-8");
		String methodType = request.getMethod();
		// 如果是OPTIONS请求 直接放行
		if(methodType.equals(HttpMethod.OPTIONS.toString())) return true;
		// 获取jwt Token
		String token = request.getHeader(tokenHeader);

		if(!(handler instanceof HandlerMethod)){
			return true;
		}

		// 获取发起类，如果是接口文档直接通行
		if(packageMatches(((HandlerMethod) handler).getBean().getClass().getName())) {
			return true;
		}

		if(token == null) {
			// 获取token不存在，未登录
			returnResult(response,DSResult.fail(ResultCode.USER_NOT_LOGIN));
			return false;
		}

		if(token.equals("") || token.equals("null")) {
			// 获取指定token失败（不携带本系统token）说明token不合法
			returnResult(response,DSResult.fail(ResultCode.TOKEN_ERROR));
			return false;
		}

		// 获取jwt
		// 前端安全规则会在token前生成head 这里进行去除
		String jwt = token.startsWith(tokenHead) ? token.substring(tokenHead.length()) : token;

		// 对jwt进行效验
		if(!tokenUtil.verifyToken(jwt)) {
			// 效验失败，说明Token已失效,重新登录
			returnResult(response,DSResult.fail(ResultCode.USER_NOT_LOGIN));
			return false;
		}

		// 获取token剩余时间(单位：分钟)
		Long expireTime = tokenUtil.getExpireTime(jwt);
		if(expireTime < 5 && expireTime != 0) {
			// 不足五分钟，进行刷新
			tokenUtil.refreshToken(jwt);
		}

		Long userId = tokenUtil.getTokenUserId(jwt);
		Object reqUserId = request.getParameter("userId");
		if(reqUserId == null){
			request.setAttribute("userId",userId);
			return  true;
		}
		else {
			if(!Long.valueOf(String.valueOf(reqUserId)).equals(userId))
				request.setAttribute("userId",userId);
		}

		// 效验通过，进行放行
		return true;
	}

	/*
	* 向前端返回信息
	* */
	private void returnResult(HttpServletResponse response, DSResult<Object> result ) {
		try {
			response.getWriter()
					.println(
							JSON.toJSONString(result)
					);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 正则匹配包名
	private boolean packageMatches(String packageName) {
		String reg = "^org\\.springdoc\\.webmvc.*";
		return packageName.matches(reg);
	}
}
